﻿using System;
using System.Collections.Generic;
using System.Text;

using log4net;
using log4net.Appender;
using log4net.Core;

using System.Net;
using System.Threading;
using log4net.Util;
using log4net.Extensions.Appender.Web.Client;

using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Net.Security;


namespace log4net.Extensions.Appender.Web
{
    public class WebServiceAppender:AppenderSkeleton
    {
        private static AutoResetEvent _EventReceived = new AutoResetEvent(false);
        private static Thread _PosterThread = null;
        private static Queue<LoggingEventMessage> _PostObjects = new Queue<LoggingEventMessage>();
        private static readonly TimeSpan _EventReceivedTimeout = new TimeSpan(0, 5, 0);

        /// <summary>
        /// Url that implements the service.
        /// </summary>
        public string ServiceUrl { get; set; }
        /// <summary>
        /// Flag to ignore certificate errors 
        /// </summary>
        public bool IgnoreCertificateErrors { get; set; }


        static WebServiceAppender()
        {
            _PosterThread = new Thread(new ThreadStart(posterMain));
            _PosterThread.IsBackground = true;
            _PosterThread.Start();
        }

        static public bool certExaminer(object sender, X509Certificate c, X509Chain chain, SslPolicyErrors sllPolicyErrors)
        {
            return true;    //true means the certificate is okay to use
        }

        static void posterMain()
        {
            ServicePointManager.ServerCertificateValidationCallback = certExaminer;

            while (true)
            {
                _EventReceived.WaitOne(_EventReceivedTimeout, false);

                LoggingEventMessage postObject = null;

                lock(_PostObjects)
                {
                    if (_PostObjects.Count == 0)
                        continue;
                    postObject = _PostObjects.Dequeue();
                }

                if (null == postObject)
                    continue;

                try
                {
                    MessageWebService service = new MessageWebService();
                    service.Url = postObject.ServiceUrl;
                    service.Record(postObject);
                }
                catch (Exception ex)
                {
                    LogLog.Error("WebServiceAppender.posterMain() - Exception posting to service", ex);
                }

            }
        }


        protected override bool RequiresLayout
        {
            get
            {
                return true;
            }
        }

        


        protected override void Append(LoggingEvent loggingEvent)
        {
            

            lock (_PostObjects)
            {
                if (_PostObjects.Count > 10000)
                    return;
                string renderedMessage = base.RenderLoggingEvent(loggingEvent);
                LoggingEventMessage message = new LoggingEventMessage(loggingEvent, renderedMessage);
                message.ServiceUrl = this.ServiceUrl;
                _PostObjects.Enqueue(message);
            }

            _EventReceived.Set();   
        }
    }
}
